package cn.vehicle.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import cn.vehicle.service.config.SystemConfig;
import cn.vehicle.service.config.SystemConfigService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * JWT 鉴权拦截器
 * <p>
 * 负责在每次请求前验证客户端提供的 JWT Token 是否有效。
 * 若 Token 缺失或已过期，则拒绝请求并返回 401 状态码。
 * </p>
 *
 * <p>主要职责：</p>
 * <ul>
 *   <li>校验请求头中 Authorization 字段的 JWT 是否存在；</li>
 *   <li>验证签名算法与过期时间；</li>
 *   <li>将用户 ID 存入 request 属性，供后续业务层获取。</li>
 * </ul>
 */
@Component
public class JwtInterceptor implements HandlerInterceptor {

    @Resource
    private SystemConfigService systemConfigService;

    /**
     * 请求预处理方法
     * <p>在 Controller 执行前进行 Token 校验。</p>
     *
     * @param request  HTTP 请求对象
     * @param response HTTP 响应对象
     * @param handler  处理器对象
     * @return true 表示验证通过，false 表示拦截请求
     * @throws Exception 当验证出现异常时抛出
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 从请求头中获取 Authorization 字段（JWT Token）
        String token = request.getHeader("Authorization");

        // 若未提供 Token，则直接返回 401 未授权错误
        if (StrUtil.isEmpty(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write("{\"code\": \"100008\",\"message\": \"未提供token,请先登录\"}");
            return false;
        }

        try {
            // 使用系统配置的密钥生成签名器，用于验证 Token 签名
            JWTSigner jwtSigner = JWTSignerUtil.hs256(systemConfigService.get(SystemConfig.jwtSecurityKey).getBytes());
            JWTValidator jwtValidator = JWTValidator.of(token);
            // 校验签名算法是否匹配
            jwtValidator.validateAlgorithm(jwtSigner);
            // 校验 Token 是否过期
            jwtValidator.validateDate();

            // 解析 Token 并提取载荷信息
            JWT jwt = JWT.of(token);
            // 将 userId 放入请求上下文，方便后续业务逻辑获取当前用户
            request.setAttribute("userId", jwt.getPayload("userId"));
        } catch (Exception e) {
            // Token 无效或过期时返回 401，并提示重新登录
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write("{\"code\": \"100009\",\"message\": \"token无效或已过期\"}");
            return false;
        }

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
}
